<template>
  <view class="page_root" data-page-name="工单详情" data-page-identification="e_0ox2505i2f">
    <!-- UNI_APP_EXEGESIS_START NAVIGATION_TEMPLATE UNI_APP_EXEGESIS_END -->
    <!-- begin vid_1paq11pftj 自定义模板_7yc4v1zutt -->
    <!-- <u-button type="primary" @click="showModal">开始1</u-button> -->
    <u-mask :show="state.loading">
      <view class="warp">
        <view class="rect" @tap.stop>加载中....</view>
      </view>
    </u-mask>
    <u-navbar
      title="工单详情"
      title-color="#fff"
      back-icon-color="#fff"
      :is-fixed="true"
      :border-bottom="false"
    >
    </u-navbar>
    <view class="detail-content">
      <view class="detail-top">
        <view class="gd-title">{{ state.gdBaseDate?.content }}</view>
        <view class="gd-number">
          <span class="number-label">工单编号：</span>
          <span class="number-value">{{ state.gdBaseDate?.number }}</span>
        </view>
        <view class="gd-status" :style="getColorStyle(state.gdBaseDate.status)">{{
          state.gdBaseDate?.status
        }}</view>
      </view>
      <view class="gd-content">
        <view class="content-title mgb24">工单详情</view>
        <view class="description">
          <view class="description-left">
            <view class="description-item" v-for="(item, index) in defaultBaseDataMap">
              <view class="description-title">{{ item.name }}</view>
              <view class="description-value">{{ state.gdBaseDate?.[item.value] }}</view>
            </view>
          </view>
        </view>

        <view class="description" v-if="state.gdBaseDateShowAll">
          <view class="description-left">
            <view class="description-item" v-for="(item, index) in conditionBaseDataMap">
              <view class="description-title">{{ item.name }}</view>
              <view class="description-value">{{ state.gdBaseDate?.[item.value] }}</view>
            </view>
          </view>
        </view>
        <view class="show-or-hide" @click="state.gdBaseDateShowAll = !state.gdBaseDateShowAll"
          >{{ state.gdBaseDateShowAll ? '收起内容' : '加载更多' }}
          <van-icon name="arrow-up" v-if="state.gdBaseDateShowAll" />
          <van-icon name="arrow-down" v-else
        /></view>
      </view>
      <view class="question-description">
        <view class="content-title mgb24">问题描述</view>
        <view
          class="description-body richtext-container"
          v-if="state.detailDescription"
          v-html="getHtmlContent(state.detailDescription)"
        ></view>
      </view>
      <view class="communication-view">
        <view class="content-title mgb24">沟通记录</view>
        <view class="communicate-msg">
          <view
            class="no-img"
            v-if="
              !state.gdDetail.workOrderRemarkDtoList ||
              state.gdDetail.workOrderRemarkDtoList.length == 0
            "
          ></view>
          <view
            v-for="(item, index) in state.gdDetail.workOrderRemarkDtoList"
            :key="index"
            class="remark-main"
          >
            <view
              :class="[
                item.createdBy === state.userInfo.name ? 'remark-body-odd' : 'remark-body-even',
              ]"
            >
              <view class="remark-top">
                <view class="remark-text richtext-container" v-html="getHtmlContent(item.content)">
                </view>
              </view>
              <view class="remark-bottom">
                <view class="remark-time">{{ item.createdTime }}</view>
                <view class="remark-people">{{ item.createdBy }}</view>
              </view>
            </view>
          </view>
        </view>

        <view class="communicate-fill">
          <view id="quillEditor" class="quill-editor" ref="quillInstance"></view>

          <u-loading class="sub-load" mode="circle" v-if="state.remarkLoading"></u-loading>
          <view class="sub-btn" @click="confirmRemark" title="提交沟通记录" v-else></view>
        </view>
      </view>
      <view class="question-description">
        <view class="content-title mgb24">问题描述</view>
        <view class="second-title">根因分析</view>
        <view
          class="root-case"
          v-if="rootState.responsibleParty || rootState.businessType || rootState.rootCauseClassify"
        >
          <view class="root-item">{{ rootState.responsibleParty }}</view>
          <view class="root-item">{{ rootState.businessType }}</view>
          <view class="root-item">{{ rootState.rootCauseClassify }}</view>
        </view>
        <view
          class="description-body richtext-container"
          v-if="state.gdBaseDate.rootCauseAnalysis"
          v-html="getHtmlContent(state.gdBaseDate.rootCauseAnalysis)"
        ></view>
        <view class="second-title mgt16 mgb16">解决方案详情</view>
        <view
          class="description-body richtext-container"
          v-if="state.gdBaseDate.solutionDetail"
          v-html="getHtmlContent(state.gdBaseDate.solutionDetail)"
        ></view>
      </view>
      <view class="question-description">
        <view class="content-title mgb24">操作记录</view>
        <scroll-view class="timeline-root" scroll-y>
          <view
            v-for="(month, mIdx) in state.gdDetail.workOrderOperateLogList"
            :key="mIdx"
            class="month-block"
          >
            <view class="month-title">{{ month.month }}</view>

            <view
              v-for="(item, idx) in month.workOrderChangeRecordList"
              :key="item.id"
              class="timeline-row"
            >
              <!-- 左侧时间 -->
              <view class="time-col">
                <!-- <view class="time-text">{{ formatTime(item.submissionTime) }}</view> -->
                <view class="time-text">{{ item.submissionTime }}</view>
              </view>

              <!-- 中间轴：dot + dashed line -->
              <view class="axis-col">
                <view class="axis-center">
                  <view class="node" :class="{ latest: mIdx === 0 && idx === 0 }"></view>

                  <!-- 竖线（最后一条不显示） -->
                  <view
                    v-if="!isLastNode(mIdx, idx)"
                    class="axis-line"
                    :class="{ hide: idx === month.workOrderChangeRecordList.length - 1 }"
                  ></view>
                </view>
              </view>

              <!-- 右侧卡片 -->
              <view class="card-col">
                <view class="card">
                  <view class="card-title">{{ item.classify }}</view>
                  <view class="card-sub">{{ item.submitter }} {{ item.content || '' }}</view>
                </view>
              </view>
            </view>
          </view>
        </scroll-view>
      </view>
      <view class="question-description">
        <view class="content-title mgb24">附件</view>
        <view class="file-body">
          <view class="file-left">
            <view
              v-for="(item, index) in newState.descriptionFileList"
              :key="index"
              class="file-icon"
              :title="item.name"
              @click="handlerClick(item)"
              >{{ item.name }}</view
            >
          </view>
          <view class="file-right">
            <span v-if="newState.descriptionFileList && newState.descriptionFileList.length > 0">
              创建时间：{{ state.gdDetail.workOrderDto.createdTime }}
            </span>
          </view>
        </view>
      </view>
    </view>
    <view class="bottom-btn">
      <OperationButton :operationForm="state.baseInformation" @refresh="getData" />
    </view>
    <!-- end vid_1paq11pftj 自定义模板_7yc4v1zutt -->
  </view>
</template>
<script setup>
  import {
    ref,
    reactive,
    toRaw,
    markRaw,
    watch,
    computed,
    onBeforeMount,
    onMounted,
    onBeforeUnmount,
    onUnmounted,
    onActivated,
    onDeactivated,
    getCurrentInstance,
  } from 'vue';
  import { useRoute } from 'vue-router';
  const route = useRoute();
  import { get, post, put, del, request, requestWithHeaders } from '@/utils/http/Axios';
  // import {
  //   cloneDeep,
  //   localGet,
  //   traversalTreeStructure,
  //   set,
  //   checkCaseCondition,
  //   throttle,
  //   merge,
  //   debounce,
  //   getGridStyle,
  //   getCellRenderAble,
  //   formulaStrategy,
  //   getApplicationId,
  //   getComponentParamsValue,
  //   get as lodashGet,
  // } from '@/utils/index';
  import {
    isEqual,
    isNullOrEmpty,
    isEmptyArr,
    isArray,
    isEmpty,
    isNullOrUnDef,
    isContained,
  } from '@/utils/is';
  import { CovertOptions, getChartsDataSourceConvert } from '@/utils/chart';
  import { handleRedirect } from '@/utils/common';
  // import {
  //   propertyFormatByNumber,
  //   propertyFormatByPercentage,
  //   propertyFormatByDate,
  //   parseSubFromDataList,
  // } from '@/utils/format';
  // import { checkCommonCondition, getResultByCurrentCommonCondition } from '@/utils/formCondition';
  // import { FormFormat } from '@/utils/formFormat'
  // import { customAddWaterMarkFunc, generateWaterMarkText } from '@/utils/addWaterMark';
  // import dayjs from 'dayjs';
  // import hashSum from 'hash-sum';
  /*** UNI_APP_EXEGESIS ***
    import { handleRedirect, permission, parseJson } from '@/utils/common';
    import { onPullDownRefresh, onLoad, onReady, onShow, onHide, onPageScroll, onUnload } from '@dcloudio/uni-app';
    import { BroadcastMessage } from '@/utils/BroadcastMessage';
    import { sendToken } from "@/hooks/useIframeToken";
    *** UNI_APP_EXEGESIS ***/

  // ---------------------------- 属性定义 ----------------------------
  const sourceId = 'page3000001011';

  // 获取传入的流程ID和组件参数
  const props = defineProps({
    processInstanceId: {
      type: [String, Number, Boolean],
      default: undefined,
    },
    hideNav: {
      type: [Boolean],
      default: undefined,
    },
  });

  // 组件参数默认值
  const componentParamsDefaultProps = {};

  // 是否显示菜单按钮
  const isMenuIconShow = false;
  // NAVIGATION_MENU
  const handleShowNavigation = () => {};

  let isProcessState = ref(false);

  const setTimeOutList = [];

  const vid_1paq11pftj_props = reactive({
    code: '',
  });

  // ============================ 属性定义 ============================

  // ---------------------------- 元素数据引用 ----------------------------
  // 组件 自定义模板_7yc4v1zutt ref 的引用
  const vid_1paq11pftj_ref = ref(null);
  // 动态key的map
  const fieldTypeMap = {};
  // 动态key的map
  const refMap = { vid_1paq11pftj_ref };

  const showState = reactive({
    vid_1paq11pftj_visible: true,
  });
  // ============================ 元素数据引用 ============================

  // ---------------------------- 数据 ----------------------------

  // ============================ 数据 ============================

  // ---------------------------- 方法 ----------------------------
  // ---------------------------- 页面数据 ----------------------------

  // ============================ 页面数据 ============================

  // ---------------------------- 数据字典 ----------------------------

  // ============================ 数据字典 ============================

  // ---------------------------- 响应 ----------------------------

  // ============================ 响应 ============================

  // ---------------------------- 函数 ----------------------------
  import { onShow } from '@dcloudio/uni-app';
  // 自定义函数 返回上一页
  const customFunction_goBack_jq45cd5yeh = (params) => {
    uni.navigateBack();
  };

  // ============================ 函数 ============================

  // ---------------------------- 页面参数 ----------------------------

  const pageParameter_state = reactive({
    processInstanceId: undefined,
  });

  // ============================ 页面参数 ============================

  // ---------------------------- 组件事件处理方法 ----------------------------

  // ============================ 组件事件处理方法 ============================

  // ============================ 方法 ============================

  // ---------------------------- 生命周期 ----------------------------
  /*** UNI_APP_EXEGESIS ***
        // 获取上一层传递的数据
        const workflowChannel = new BroadcastMessage('WORKFLOW');
        workflowChannel.publish({ status: 'Ready' });
        workflowChannel.subscribe((data) => {
          if (data) {
            isProcessState.value = (window.self !== window.parent && data.type === 'hideHeader');
          }
        });
        *** UNI_APP_EXEGESIS ***/

  const pageScrollTop = ref(0);

  // *** PREVIEW_EXEGESIS ***
  onMounted(() => {
    setPageParams(route.query);
    // 设置表单的rule
    try {
    } catch {
      // do nothing
    }
  });
  // *** PREVIEW_EXEGESIS *** //

  /*** UNI_APP_EXEGESIS ***
    const routeOption = ref({})
    onLoad((option) => {
      routeOption.value = option;
    });
    onReady(() => {
      setPageParams(routeOption.value)
      // 设置表单的rule
      try{

      }catch{
          // do nothing
      }
    });
    // 图表刷新标记
    const uChartsReshowFlag = ref(false);
    onHide(() => { // 页面隐藏后标记置为false(如果不置为false无法触发图表更新)
        uChartsReshowFlag.value = false
    })
    onShow(() => {
        uChartsReshowFlag.value = true; // 页面激活后,标记置为true

        setPageParams(routeOption.value)
    })
    onPageScroll(e => {
        pageScrollTop.value = e.scrollTop
    });
    *** UNI_APP_EXEGESIS ***/

  let setPageParams = (routerParam) => {
    const pageParams = [{ dataType: 'STRING', name: 'processInstanceId' }];
    const strategyMap = {
      STRING: (param, paramValue) => {
        pageParameter_state[param.name] = paramValue;
      },
      BOOLEAN: (param, paramValue) => {
        if ('true' === (paramValue || '').toLowerCase()) {
          pageParameter_state[param.name] = true;
        } else if ('false' === (paramValue || '').toLowerCase()) {
          pageParameter_state[param.name] = false;
        } else {
          // TODO: 是否要支持toast
          console.error('参数传入错误！类型不匹配！');
        }
      },
      NUMBER: (param, paramValue) => {
        if (!isNaN(paramValue)) {
          pageParameter_state[param.name] = Number(paramValue);
        } else {
          // TODO: 是否要支持toast
          console.error('参数传入错误！类型不匹配！');
        }
      },
      ARRAY: (param, paramValue) => {
        if (isNullOrUnDef(paramValue) || !paramValue || paramValue === 'undefined') {
          // default value
          pageParameter_state[param.name] = [];
        } else if (paramValue.trim().startsWith('[') && paramValue.trim().endsWith(']')) {
          try {
            pageParameter_state[param.name] = JSON.parse(decodeURI(paramValue));
          } catch (error) {
            console.error('参数解析失败 ', error);
          }
        } else {
          console.error('参数传入错误！类型不匹配！');
        }
      },
    };
    pageParams.forEach((param) => {
      strategyMap[param.dataType](param, routerParam[param.name]);
    });
  };

  onUnmounted(() => {
    // 销毁定时器
    setTimeOutList.forEach(({ repeat, timer }) => {
      repeat ? clearInterval(timer) : clearTimeout(timer);
    });
  });

  /*** UNI_APP_EXEGESIS ***
    onPullDownRefresh(() => {
      // 下拉刷新
      setTimeout(() => {
          uni.stopPullDownRefresh()
      }, 1000)
    })
    *** UNI_APP_EXEGESIS ***/

  // ============================ 生命周期 ============================

  // ---------------------------- 数据关联处理 ----------------------------
  // ---------------------------- 组件数据同步 ----------------------------

  // ============================ 组件数据同步 ============================
  //
  // ============================ 数据关联处理 ============================

  // ---------------------- 不同组件自定义的处理逻辑 ---------------------

  // ====================== 不同组件自定义的处理逻辑 ======================

  // ================================定制化逻辑========================================
  import OperationButton from '../Page3000001237/Page3000001237.vue';
  import { showToast, showFailToast, showSuccessToast } from 'vant';
  import Quill from 'quill';
  import '@vueup/vue-quill/dist/vue-quill.snow.css';
  import 'quill/dist/quill.snow.css';
  // 按需导入 Vant 3 组件
  import {
    Form,
    Field,
    CellGroup,
    Picker,
    Popup,
    Uploader,
    Button,
    DatePicker,
    Toast,
    Col,
    Cell,
    Row,
    Icon,
    DropdownMenu,
    DropdownItem,
    ConfigProvider,
  } from 'vant';
  import 'vant/lib/index.css';
  // 页面内注册 Vant 组件
  const { appContext } = getCurrentInstance();
  [
    ['van-form', Form],
    ['van-field', Field],
    ['van-cell-group', CellGroup],
    ['van-cell', Cell],
    ['van-picker', Picker],
    ['van-popup', Popup],
    ['van-uploader', Uploader],
    ['van-button', Button],
    ['van-date-picker', DatePicker],
    ['van-col', Col],
    ['van-row', Row],
    ['van-icon', Icon],
    ['van-config-provider', ConfigProvider],

    ['van-dropdown-menu', DropdownMenu],
    ['van-dropdown-item', DropdownItem],
  ].forEach(([name, comp]) => appContext.app.component(name, comp));
  const titleRef = ref(null);
  const contentPaddingTop = ref('0px');
  import { nextTick } from 'vue';
  import { color } from 'echarts';

  onMounted(async () => {
    setPageStyle('gdxq-page');
    const queryString = window.location.search;

    // // 使用 URLSearchParams 解析参数字符串
    const urlParams = new URLSearchParams(queryString);

    // // 获取特定参数的值
    const id = urlParams.get('id');
    console.log(id, 'id');
    state.detailId = id;
    getAllUser();
    initQuill();
    getData();
    nextTick(() => {
      bindImagePreview();
    });
    getUserInfo();
  });
  const bgUrl = '';
  function setPageStyle(newClass) {
    // #ifdef H5
    // 仅在 H5 执行
    const appDiv = document.querySelector('#app');
    if (appDiv) {
      appDiv.className = '';

      // 再添加当前需要的类
      if (newClass) {
        appDiv.classList.add(newClass);
      }
    }

    const topHeader = document.querySelector('.uni-page-head');
    if (topHeader) topHeader.remove();

    const wrapper = document.querySelector('uni-page-wrapper');
    if (wrapper) wrapper.style.height = '100%';
    // #endif

    // #ifdef MP
    // 小程序端执行（如果你要做兼容逻辑，可以写这里）
    console.log('当前是小程序环境，不需要处理头部或背景');
    // #endif
  }
  const colorMap = {
    未开始: { color: '#fff', backgroundColor: '#A9A9A9 !important' },
    已解决: { color: '#fff', backgroundColor: '#52C41A !important' },
    解决中: { color: '#fff', backgroundColor: '#3875ff  !important' },
    无需解决: { color: '#fff', backgroundColor: '#FFC900  !important' },
    已关闭: { color: '#fff', backgroundColor: '#262626 !important' },
    已回访: { color: '#fff', backgroundColor: '#9254DE !important' },
    待分发: { color: '#fff', backgroundColor: '#FF7D27 !important' },
  };
  function getColorStyle(status) {
    return colorMap[status] || '#262626';
  }
  function bindImagePreview() {
    const imgs = document.querySelectorAll('.previewable-image');
    if (!imgs.length) return;

    imgs.forEach((img) => {
      img.style.cursor = 'pointer';
      img.onclick = () => {
        const urls = Array.from(imgs).map((i) => i.src);
        uni.previewImage({
          urls,
          current: img.src,
        });
      };
    });
  }

  const showPopup = ref(false);
  const checkedList = ref([]);
  function showModal() {
    console.log('11111');

    showPopup.value = true;
  }
  function getAllUser() {
    get('/solution-ppm/api/v2/built-in-system-ppm/pmgf/get/allUser').then((data) => {
      if (data.code !== 200) {
        message.error(data.message);
        return;
      }
      state.allUser = data.data.userDtoList;
    });
  }
  // 提交勾选数据
  const submitSelection = () => {
    const selected = dataList.value.filter((item) => checkedList.value.includes(item.sopStepId));

    const result = {
      children: selected.map((item) => ({
        ...item,
        rowSpan: dataList.value.length,
      })),
    };

    console.log('提交数据:', result);
    uni.showToast({
      title: data.message,
      icon: 'error',
    });
    showPopup.value = false;
  };
  const state = reactive({
    detailId: undefined,
    dataList: [],
    fileVisible: false,
    fileDetailVisible: false,
    addRemarkVisible: false,
    backRemarkVisible: false,
    remarkTitle: '',
    remarkMsg: '',
    remarkVisible: false,
    remarkList: [],
    remarkAttachmentList: [],
    changeStatusVisible: false,
    modalForm: {
      parentId: undefined,
      content: undefined,
      type: undefined,
      priority: undefined,
      questionSource: undefined,
      workHours: undefined,
      endTime: undefined,
      areaCode: undefined,
      projectId: undefined,
      milepostId: undefined,
      customer: undefined,
      production: undefined,
      environment: undefined,
      description: undefined,
      solverList: [],
      descriptionAttachmentList: [],
      quillData: '',
    },
    tableData: [],
    allUser: [],
    editSonVisible: false,
    modalTitle: '',
    gdDetail: {},
    gdBaseDate: {},
    gdBaseDateShowAll: false,
    baseInformation: {},
    changeStatusForm: {
      status: undefined,
      reason: '',
      attachmentList: [],
      workOrderId: undefined,
      solution: undefined,
    },
    sonLoading: false,
    remarkLoading: false,
    detailDescription: {},
    changeStausList: [
      {
        label: '正在处理',
        value: '正在处理',
      },
      {
        label: '已解决',
        value: '已解决',
      },
      {
        label: '无需解决',
        value: '无需解决',
      },
      {
        label: '申请流转',
        value: '申请流转',
      },
    ],
    deleteVisible: false,
    detailVisible: false,
    detailTitle: '',
    //   是否是回复父亲备注
    previewImage: '',
    previewVisible: false,
    userInfo: {},
  });
  function getUserInfo() {
    get('/base/api/v1/user/userinfo').then((data) => {
      if (data.status !== 'success') {
        state.userInfo = {};
        return;
      }
      state.userInfo = data.data.userItem;
    });
  }
  watch(
    () => state.gdDetail.workOrderRemarkDtoList,
    () => nextTick(bindImagePreview),
    { deep: true },
  );
  //     新需求
  const newState = reactive({
    descriptionFileList: [],
    solveFileList: [],
    //   解决方案概述
    solution: '',
    changeStatusLoading: false,
    isExpandAll: false,
    circulationVisible: false,
    resolvingVisible: false,
    resolvedVisible: false,
    circulationForm: {
      solverList: [],
      status: '未开始',
    },
    resolvingForm: {
      solution: '',
      status: '解决中',
      solutionDetail: '',
    },
    resolvedForm: {
      solution: '',
      attachmentList: [],
      status: '已解决',
      solutionDetail: '',
    },
    closeForm: {
      status: '关闭',
    },
    workOrderId: undefined,
    saveLoading: false,
  });
  //     根因分析
  const rootState = reactive({
    problemBelongTo: undefined,
    belongList: [],
    rootCauseClassify: [],
    tagList: [],
    rootCauseFlag: false,
  });
  const defaultBaseDataMap = [
    {
      name: ' 问题来源',
      value: 'questionSource',
    },
    {
      name: ' 优先级',
      value: 'priority',
    },
    {
      name: ' 工单类型',
      value: 'type',
    },
    {
      name: ' 创建时间',
      value: 'createdTime',
    },
    {
      name: ' 创建人',
      value: 'createdBy',
    },
    {
      name: ' 解决人',
      value: 'solver',
    },
  ];
  const conditionBaseDataMap = [
    {
      name: ' PMO',
      value: 'pmo',
    },
    {
      name: ' 所属区域',
      value: 'areaName',
    },
    {
      name: ' 所属客户',
      value: 'customer',
    },
    {
      name: ' 所属项目',
      value: 'projectName',
    },
    {
      name: ' 项目阶段',
      value: 'milepostName',
    },
    {
      name: ' 所属任务',
      value: 'taskName',
    },
    {
      name: ' 所属环境',
      value: 'environment',
    },
    {
      name: ' 所属产品',
      value: 'production',
    },
    {
      name: ' 计划解决时间',
      value: 'endTime',
    },
    {
      name: ' 实际解决时间',
      value: 'finishTime',
    },
  ];
  function getData() {
    if (!state.detailId) {
      return;
    }
    get(`/solution-ppm-work-order/api/v1/work_order/details/${state.detailId}`).then((data) => {
      if (data.code !== 200) {
        showFailToast(data.message);
        return;
      }

      state.gdDetail = data.data;
      state.gdBaseDate = data.data.workOrderDto;
      state.baseInformation = data.data.workOrderDto;
      rootState.rootCauseFlag = data.data.workOrderDto.rootCauseFlag;
      try {
        state.detailDescription = JSON.parse(data.data.workOrderDto.description);
      } catch (e) {
        console.warn('description 解析失败', e);
      }

      try {
        const solutionDetail = JSON.parse(data.data.workOrderDto.solutionDetail);
        const rootDetail = JSON.parse(data.data.workOrderDto.rootCauseAnalysis);

        // 即使第一个报错也不影响第二个执行
        try {
          solutionQuillEditor.value.setContents(solutionDetail);
        } catch (e) {
          console.warn('设置 solutionQuillEditor 报错:', e);
        }
      } catch (e) {
        console.warn('solutionDetail 解析失败', e);
      }

      newState.solution = data.data.workOrderDto.solution;
      state.tableData = data.data.workOrderOperateLogList;
      newState.descriptionFileList = data.data.workOrderDto.descriptionAttachmentList;
      newState.solveFileList = data.data.workOrderDto.attachmentList;
      rootState.rootCauseClassify = data.data.workOrderDto.rootCauseClassify || undefined;
      rootState.responsibleParty = data.data.workOrderDto.responsibleParty || undefined;
      rootState.businessType = data.data.workOrderDto.businessType || undefined;
    });
  }

  // 格式化兼容pc移动
  function getHtmlContent(input) {
    if (!input) return '';
    let delta = null;

    try {
      delta = typeof input === 'string' ? JSON.parse(input) : input;
    } catch (e) {
      return `<view>${String(input).replace(/\n/g, '<br/>')}</view>`;
    }

    if (!delta?.ops) return '';

    let html = '';
    delta.ops.forEach((op) => {
      if (op.insert?.image) {
        html += `<img src="${op.insert.image}" class="previewable-image" />`;
      } else if (typeof op.insert === 'string') {
        html += `<p>${op.insert.replace(/\n/g, '<br/>')}</p>`;
      }
    });

    return `<view style="text-align:left;">${html}</view>`;
  }

  const isQuillReady = ref(false);
  async function initQuill() {
    console.log('开始初始化 Quill');

    // 先销毁可能存在的旧实例
    // destroyQuill();

    await nextTick();

    const el = document.getElementById('quillEditor');
    console.log('找到的编辑器元素:', el);

    if (!el) {
      console.error('❌ 编辑器元素未找到');
      return;
    }

    try {
      quillEditor.value = new Quill(el, {
        modules: {
          toolbar: [['image']],
          clipboard: true,
        },
        theme: 'snow',
      });

      isQuillReady.value = true;
      console.log('✅ Quill 初始化成功', quillEditor.value);
      console.log('Quill 实例方法:', Object.keys(quillEditor.value));
    } catch (error) {
      console.error('❌ Quill 初始化失败:', error);
      isQuillReady.value = false;
    }
  }

  // 将 dataURL 转换为 File 对象的辅助函数
  const dataURLtoFile = (dataurl, filename) => {
    const arr = dataurl.split(',');
    const mime = arr[0].match(/:(.*?);/)[1];
    const bstr = atob(arr[1]);
    let n = bstr.length;
    const u8arr = new Uint8Array(n);
    while (n--) {
      u8arr[n] = bstr.charCodeAt(n);
    }
    return new File([u8arr], filename, { type: mime });
  };
  // 上传api
  const uploadFileAPI = async (file) => {
    // 构造 FormData
    const formData = new FormData();
    formData.append('file', file.file || file.originFileObj || file);

    // 打印验证一下
    for (let [key, value] of formData.entries()) {
      console.log('FormData内容:', key, value);
    }

    try {
      const res = await fetch('/file-storage/api/v1/file/upload', {
        method: 'POST',
        body: formData, // ✅ 真正传文件流
        // ⚠️ 不要手动设置 Content-Type，让浏览器自动加 boundary
        // headers: { 'Content-Type': 'multipart/form-data' }, ❌
      });

      if (!res.ok) {
        throw new Error(`上传失败: ${res.status}`);
      }

      const data = await res.json();
      console.log('上传返回:', data);

      // 按你之前接口结构封装返回
      return { data: { fullUrl: data.data.fullUrl } };
    } catch (err) {
      console.error('上传图片出错:', err);
      throw err;
    }
  };

  // 子组件
  const remarkQuillRef = ref(null);
  async function confirmRemark() {
    state.remarkLoading = true;
    const deltaContent = quillEditor.value.getContents();
    const imageUploadPromises = [];

    deltaContent.ops.forEach((op) => {
      if (op.insert && op.insert.image && op.insert.image.startsWith('data:')) {
        const localSrc = op.insert.image;

        // 如果是 base64 图片，上传并替换为 URL
        const file = dataURLtoFile(localSrc, 'image.png'); // 将 base64 转换为 File 对象

        const uploadPromise = uploadFileAPI(file).then(({ data: { fullUrl } }) => {
          // 替换 op 中的 base64 URL 为服务器返回的 URL
          op.insert.image = fullUrl;
        });

        imageUploadPromises.push(uploadPromise);
      }
    });

    try {
      await Promise.all(imageUploadPromises);

      const params = {
        workOrderId: state.detailId,
        content: JSON.stringify(deltaContent),
      };
      post('/solution-ppm-work-order/api/v1/work_order/remark', params)
        .then((data) => {
          if (data.code !== 200) {
            message.error(data.message);
            return;
          }
          showSuccessToast(data.message);
          state.addRemarkVisible = false;
          getData();
          nextTick(() => {
            quillEditor.value.setContents('');
          });
        })
        .finally(() => {
          state.remarkLoading = false;
        });
    } catch (error) {
      state.remarkLoading = false;
      console.error('图片上传失败', error);
      return; // 终止提交
    }
  }
  onShow(() => {
    getData();
  });
  function isLastNode(mIdx, idx) {
    const month = state.gdDetail.workOrderOperateLogList[mIdx];
    if (!month) return false;
    const isLastMonth = mIdx === state.gdDetail.workOrderOperateLogList.length - 1;
    const isLastIndex = idx === month.workOrderChangeRecordList.length - 1;
    return isLastMonth && isLastIndex;
  }
  function handlerDownload(item) {
    pageLoading.loading = true;
    pageLoading.tip = '文件下载中...';
    fetch(item.url)
      .then((response) => response.blob())
      .then((blob) => {
        const downloadLink = document.createElement('a');
        const url = URL.createObjectURL(blob);
        downloadLink.href = url;
        downloadLink.setAttribute('download', item.name);
        downloadLink.style.display = 'none';
        document.body.appendChild(downloadLink);
        downloadLink.click();
        document.body.removeChild(downloadLink);

        // Release the object URL after the download
        URL.revokeObjectURL(url);
        pageLoading.loading = false;
      })
      .catch((err) => {
        console.error('Download failed', err);
      });
  }
  // 判断是否是图片
  const isImage = (file) => {
    const imgExt = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];
    const ext = file.name.split('.').pop().toLowerCase();
    return imgExt.includes(ext);
  };

  // 点击处理
  const handlerClick = (file) => {
    if (isImage(file)) {
      previewImage(file);
    } else {
      downloadFile(file);
    }
  };

  // 预览图片（兼容H5和小程序）
  const previewImage = (file) => {
    if (process.env.UNI_PLATFORM === 'h5') {
      // H5直接打开图片新窗口预览
      window.open(file.url, '_blank');
    } else {
      // 小程序使用uni.previewImage
      uni.previewImage({
        urls: [file.url],
        current: file.url,
      });
    }
  };

  // 下载文件（兼容H5和小程序）
  const downloadFile = (file) => {
    if (process.env.UNI_PLATFORM === 'h5') {
      // H5通过创建a标签下载
      const link = document.createElement('a');
      link.href = file.url;
      link.download = file.name;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
    } else {
      // 小程序先下载，再打开文件（示例以微信小程序为例）
      uni.downloadFile({
        url: file.url,
        success(res) {
          if (res.statusCode === 200) {
            uni.openDocument({
              filePath: res.tempFilePath,
              success() {
                console.log('打开文档成功');
              },
            });
          }
        },
      });
    }
  };
</script>
<style lang="less" scoped>
  .page_root {
    min-height: 100%;
    box-sizing: border-box;
    overflow: auto;
    background-image: url('http://10.40.0.33:9001/file-storage/539771854764980224-source.png');
    background-repeat: no-repeat;
    background-size: cover;
    background-position: center;
    overflow: hidden !important;
  }

  .detail-content {
    height: calc(100vh - 290rpx);
    padding: 40rpx;
    position: relative;
    overflow-y: scroll;
  }
  :deep(.u-navbar) {
    background-color: transparent !important;
    padding: 0 40rpx 0 0;
    border: none;
  }
  .detail-top {
    margin-top: 40rpx;
  }
  .gd-title {
    font-size: 32rpx;
    color: #ffffff;
    line-height: 46rpx;
    font-weight: 600;
    margin-bottom: 16rpx;
  }
  .gd-number {
    margin-bottom: 16rpx;
  }
  .number-label {
    font-size: 24rpx;
    color: rgba(255, 255, 255, 0.8);
    text-align: left;
    line-height: 32rpx;
    font-weight: 400;
  }
  .number-value {
    font-family: PingFangSC-Semibold;
    font-size: 24rpx;
    color: #ffffff;
    text-align: left;
    line-height: 32rpx;
    font-weight: 600;
  }
  .gd-content {
    background-image: url('http://10.40.0.33:9001/file-storage/539948536792692736-source.png');
    background-size: cover;
    padding: 24rpx;
    border: 2rpx solid rgba(255, 255, 255, 1);
    border-radius: 16rpx;
    padding-bottom: 48rpx;
    position: relative;
    margin-bottom: 20rpx;
  }
  .content-title {
    font-size: 32rpx;
    color: rgba(0, 0, 0, 0.85);
    font-weight: 600;
  }
  .mgb24 {
    margin-bottom: 24rpx;
  }
  .pd24 {
    padding: 24rpx;
  }
  .description {
    display: flex;
    justify-content: space-between;
  }
  .show-or-hide {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    bottom: 24rpx;
    font-size: 24rpx;
    color: rgba(0, 0, 0, 0.45);
    font-weight: 400;
  }
  .description-left {
    flex: 1;
    display: flex;
    flex-wrap: wrap; /* 可换行，防止超出 */
    justify-content: space-between; /* 两个之间留间距 */
  }
  .description-item {
    margin-bottom: 16rpx;
    width: 50%;
  }
  .description-title {
    font-size: 24rpx;
    color: rgba(0, 0, 0, 0.45);
    font-weight: 400;
    margin-bottom: 8rpx;
  }
  .description-value {
    font-size: 28rpx;
    color: rgba(0, 0, 0, 0.85);
    font-weight: 400;
  }
  .question-description {
    margin-bottom: 32rpx;
    border-radius: 16rpx;
    background-image: url('http://10.40.0.33:9001/file-storage/539953617021777920-source.png');
    background-size: cover;
    padding: 24rpx;
  }
  .description-body {
    border-radius: 16rpx;
    background: rgba(51, 102, 255, 0.06);
    padding: 24rpx;
  }
  .communication-view {
    padding: 24rpx;
    background-image: url('http://10.40.0.33:9001/file-storage/539955621062326272-source.png');
    background-size: cover;
    position: relative;
    margin-bottom: 32rpx;
  }
  .communicate-msg {
    max-height: 582rpx;
    overflow-y: auto;
    overflow-x: hidden;
    margin-bottom: 16rpx;
    padding-right: 6rpx;
    position: relative;
  }

  .no-img {
    width: 66rpx;
    height: 80rpx;
    background-image: url('http://10.40.0.33:9001/file-storage/482099304502618112-source.png');
    background-size: cover;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }
  .communicate-fill {
    position: relative;
    border-radius: 4rpx;
    padding: 0 5rpx;
    border: 1px solid #3875ff;
    min-height: 300rpx;
  }

  .sub-btn {
    background-image: url('http://10.40.0.33:9001/file-storage/518746950211022848-source.png');
    background-size: cover;
    width: 32rpx;
    height: 32rpx;
    cursor: pointer;
    position: absolute;
    right: 20rpx;
    bottom: 20rpx;
  }
  .sub-load {
    width: 32rpx;
    height: 32rpx;
    cursor: pointer;
    position: absolute;
    right: 20rpx;
    bottom: 20rpx;
  }
  .msg-uploader {
    margin-top: 20rpx;
  }
  .remark-body-odd {
    margin-bottom: 16px;
    text-align: right;
    .remark-bottom {
      display: flex;
      gap: 16rpx;
      justify-content: end;
    }
    .remark-top {
      margin-bottom: 8px;
      border-radius: 16rpx 16rpx 16rpx;
      background: rgba(51, 102, 255, 0.06);
    }
  }
  .remark-body-even {
    margin-bottom: 16px;
    text-align: left;
    .remark-bottom {
      display: flex;
      gap: 8rpx;
      justify-content: start;
    }
    .remark-top {
      background: rgba(56, 172, 255, 0.15);
      margin-bottom: 16rpx;
    }
  }
  .remark-top {
    border-radius: 4px 0 4px 4px;
    padding: 8rpx 16rpx;
    display: inline-block;
  }
  .remark-time {
    font-size: 12px;
    color: #595959;
    letter-spacing: 0;
    font-weight: 400;
  }
  .remark-people {
    font-size: 24rpx;
    color: #3875ff;
    letter-spacing: 0;
    text-align: right;
    font-weight: 400;
  }
  .people-label {
    font-size: 14px;
    color: #595959;
    letter-spacing: 0;
    text-align: right;
    font-weight: 400;
  }
  .people-content {
    font-size: 28rpx;
    letter-spacing: 0;
    font-weight: 500;
  }
  .communicate-fill :deep(.ql-editor) {
    padding: 5rpx;
  }
  .communicate-fill :deep(.ql-toolbar) {
    //display: none;
    border: none;
    height: 0;
    padding: 0 !important;
  }
  .communicate-fill :deep(.ql-toolbar .ql-image) {
    display: block;
    width: 120rpx;
    height: 20px;
    border: none;
    z-index: 900;
    position: absolute;
    bottom: 20rpx;
    right: 70rpx;
    background:transparent;
    padding: 0;
  }
  .quill-editor {
    min-height: 200rpx;
  }
  :deep(.quill-editor .ql-container) {
    height: auto !important;
  }
  :deep(.quill-editor .ql-editor) {
    height: auto !important;
    overflow-y: visible !important;
    min-height: 200rpx !important;
  }

  :deep(.ql-toolbar .ql-formats .ql-bold) {
    display: none !important;
  }

  :deep(.ql-toolbar .ql-formats .ql-italic) {
    display: none !important;
  }
  :deep(.ql-toolbar .ql-formats .ql-active) {
    display: none !important;
  }
  :deep(.ql-toolbar .ql-formats .ql-underline) {
    display: none !important;
  }
  :deep(.ql-toolbar .ql-formats .ql-clean) {
    display: none !important;
  }
  :deep(.ql-toolbar .ql-formats .ql-color) {
    display: none !important;
  }
  :deep(.ql-toolbar .ql-formats .ql-picker) {
    display: none !important;
  }

  .communicate-fill :deep(.ql-blank) {
    border-radius: 4rpx;
  }
  .communicate-fill :deep(.ql-toolbar) {
    padding: 5rpx;
    border-radius: 4rpx;
  }
  .communicate-fill :deep(.ql-container) {
    border: none;
    border-radius: 4rpx;
  }

  :deep(.ql-formats svg) {
    width: 42rpx;
    height: 42rpx;
  }
  .richtext-container :deep(img) {
    max-width: 100%;
    height: auto;
    display: block;
    margin: 8rpx 0;
    border-radius: 6rpx;
  }
  .second-title {
    font-size: 28rpx;
    color: rgba(0, 0, 0, 0.85);
    font-weight: 400;
    margin-bottom: 16rpx;
  }
  .root-case {
    display: flex;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 15rpx;
    margin-bottom: 16rpx;
  }
  .root-item {
    border-radius: 32rpx;
    background: rgba(255, 255, 255, 0.89);
    padding: 12rpx 32rpx;
  }
  .mgt16 {
    margin-top: 16rpx;
  }
  .mgb16 {
    margin-bottom: 16rpx;
  }
  /* 根容器（仅作用于本组件） */
  .timeline-root {
    padding: 30rpx;
    background: #f6f8fb; /* 页面背景 */
    min-height: 100%;
  }

  /* 月标题 */
  .month-block + .month-block {
    margin-top: 40rpx;
  }
  .month-title {
    font-size: 30rpx;
    color: #6b7aa4;
    font-weight: 600;
    margin-bottom: 24rpx;
  }

  /* 每一行（时间轴项） */
  .timeline-row {
    display: flex;
    align-items: center;
    margin-bottom: 28rpx;
  }

  /* 左侧时间列 */
  .time-col {
    width: 200rpx; /* 根据需要调整 */
    padding-top: 6rpx;
  }
  .time-text {
    font-size: 24rpx;
    color: #8c94a8;
  }

  /* 中间轴列 */
  .axis-col {
    width: 40rpx;
    display: flex;
    justify-content: center;
    position: relative;
  }
  .axis-center {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 100%;
  }

  /* 节点样式
   latest 类表示最顶上的节点（高亮，空心蓝点 + 外圈）
*/
  .node {
    width: 16rpx;
    height: 16rpx;
    border-radius: 50%;
    background: #fff;
    border: 4rpx solid #bfc8e8; /* 默认灰色外圈 */
    box-sizing: border-box;
  }

  /* 竖直虚线（使用 repeating-linear-gradient 实现点状线） */
  .axis-line {
    width: 2rpx;
    margin-top: 8rpx;
    margin-bottom: 0;
    flex: 1; /* 让线竖直拉伸以占剩余高度 */
    background-image: repeating-linear-gradient(
      to bottom,
      rgba(51, 102, 255, 0.25),
      rgba(51, 102, 255, 0.25) 2rpx,
      transparent 2rpx,
      transparent 8rpx
    );
    border-radius: 1rpx;
  }

  /* 右侧卡片 */
  .card-col {
    flex: 1;
    padding-left: 24rpx;
  }
  .card {
    background: linear-gradient(180deg, rgba(243, 249, 255, 0.9), rgba(247, 252, 255, 0.95));
    border-radius: 12rpx;
    padding: 18rpx 20rpx;
    box-shadow: 0 4rpx 12rpx rgba(34, 60, 80, 0.06);
  }
  .card-title {
    font-size: 30rpx;
    color: #173d82;
    font-weight: 700;
    margin-bottom: 8rpx;
  }
  .card-sub {
    font-size: 24rpx;
    color: #7a859e;
    line-height: 1.5;
  }

  /* 手机端溢出处理 */
  @media (max-width: 480px) {
    .time-col {
      width: 160rpx;
    }
    .card-title {
      font-size: 28rpx;
    }
    .card-sub {
      font-size: 22rpx;
    }
  }
  .file-left {
    text-align: right;
    color: #3875ff;
    text-decoration: underline;
  }

  .file-right {
    text-align: right;
    font-size: 20rpx;
  }
  .right-top {
    padding: 20px 24px;
    background-color: #fff;
    border-radius: 4px;
    //height: 100px;
  }
  .bottom-btn {
    padding: 0 40rpx;
    margin-top: 32rpx;
  }
  .gd-status {
    border-radius: 16rpx;
    background: #3366ff;
    padding: 2rpx 16rpx;
    margin-bottom: 24rpx;
    width: 160rpx;
    text-align: center;
    font-size: 28rpx;
    font-weight: 400;
  }
</style>
